1 using UnityEngine;
2 using
System.Collections;
3
4 namespace
Completed
5 {
6     
//The abstract keyword enables you to create classes and class members that are incomplete and must be implemented in a derived class.
7     
public abstract class MovingObject : MonoBehaviour
8     {
9         
public float moveTime = 0.1f; //Time it will take object to move, in seconds.
10         
public LayerMask blockingLayer; //Layer on which collision will be checked.
11         
12         
13         
private BoxCollider2D boxCollider; //The BoxCollider2D component attached to this object.
14         
private Rigidbody2D rb2D; //The Rigidbody2D component attached to this object.
15         
private float inverseMoveTime; //Used to make movement more efficient.
16         
17         
18         
//Protected, virtual functions can be overridden by inheriting classes.
19         
protected virtual void Start ()
20         {
21             
//Get a component reference to this object's BoxCollider2D
22             boxCollider = GetComponent <BoxCollider2D> ();
23             
24             
//Get a component reference to this object's Rigidbody2D
25             rb2D = GetComponent <Rigidbody2D> ();
26             
27             
//By storing the reciprocal of the move time we can use it by multiplying instead of dividing, this is more efficient.
28             inverseMoveTime =
1f / moveTime;
29         }
30         
31         
32         
//Move returns true if it is able to move and false if not.
33         
//Move takes parameters for x direction, y direction and a RaycastHit2D to check collision.
34         
protected bool Move (int xDir, int yDir, out RaycastHit2D hit)
35         {
36             
//Store start position to move from, based on objects current transform position.
37             Vector2 start = transform.position;
38             
39             
// Calculate end position based on the direction parameters passed in when calling Move.
40             Vector2 end = start +
new Vector2 (xDir, yDir);
41             
42             
//Disable the boxCollider so that linecast doesn't hit this object's own collider.
43             boxCollider.enabled =
false;
44             
45             
//Cast a line from start point to end point checking collision on blockingLayer.
46             hit = Physics2D.Linecast (start, end, blockingLayer);
47             
48             
//Re-enable boxCollider after linecast
49             boxCollider.enabled =
true;
50             
51             
//Check if anything was hit
52             
if(hit.transform == null)
53             {
54                 
//If nothing was hit, start SmoothMovement co-routine passing in the Vector2 end as destination
55                 StartCoroutine (SmoothMovement (end));
56                 
57                 
//Return true to say that Move was successful
58                 
return true;
59             }
60             
61             
//If something was hit, return false, Move was unsuccesful.
62             
return false;
63         }
64         
65         
66         
//Co-routine for moving units from one space to next, takes a parameter end to specify where to move to.
67         
protected IEnumerator SmoothMovement (Vector3 end)
68         {
69             
//Calculate the remaining distance to move based on the square magnitude of the difference between current position and end parameter.
70             
//Square magnitude is used instead of magnitude because it's computationally cheaper.
71             
float sqrRemainingDistance = (transform.position - end).sqrMagnitude;
72             
73             
//While that distance is greater than a very small amount (Epsilon, almost zero):
74             
while(sqrRemainingDistance > float.Epsilon)
75             {
76                 
//Find a new position proportionally closer to the end, based on the moveTime
77                 Vector3 newPostion = Vector3.MoveTowards(rb2D.position, end, inverseMoveTime * Time.deltaTime);
78                 
79                 
//Call MovePosition on attached Rigidbody2D and move it to the calculated position.
80                 rb2D.MovePosition (newPostion);
81                 
82                 
//Recalculate the remaining distance after moving.
83                 sqrRemainingDistance = (transform.position - end).sqrMagnitude;
84                 
85                 
//Return and loop until sqrRemainingDistance is close enough to zero to end the function
86                 
yield return null;
87             }
88         }
89         
90         
91         
//The virtual keyword means AttemptMove can be overridden by inheriting classes using the override keyword.
92         
//AttemptMove takes a generic parameter T to specify the type of component we expect our unit to interact with if blocked (Player for Enemies, Wall for Player).
93         
protected virtual void AttemptMove <T> (int xDir, int yDir)
94             
where T : Component
95         {
96             
//Hit will store whatever our linecast hits when Move is called.
97             RaycastHit2D hit;
98             
99             
//Set canMove to true if Move was successful, false if failed.
100             
bool canMove = Move (xDir, yDir, out hit);
101             
102             
//Check if nothing was hit by linecast
103             
if(hit.transform == null)
104                 
//If nothing was hit, return and don't execute further code.
105                 
return;
106             
107             
//Get a component reference to the component of type T attached to the object that was hit
108             T hitComponent = hit.transform.GetComponent <T> ();
109             
110             
//If canMove is false and hitComponent is not equal to null, meaning MovingObject is blocked and has hit something it can interact with.
111             
if(!canMove && hitComponent != null)
112                 
113                 
//Call the OnCantMove function and pass it hitComponent as a parameter.
114                 OnCantMove (hitComponent);
115         }
116         
117         
118         
//The abstract modifier indicates that the thing being modified has a missing or incomplete implementation.
119         
//OnCantMove will be overriden by functions in the inheriting classes.
120         
protected abstract void OnCantMove <T> (T component)
121             
where T : Component;
122     }
123 }


The abstract keyword enables you to create classes and class members that are incomplete and must be implemented in a derived class.

public float moveTime = 0.1f; Time it will take object to move, in seconds.

public LayerMask blockingLayer; Layer on which collision will be checked.

private BoxCollider2D boxCollider; The BoxCollider2D component attached to this object.

private Rigidbody2D rb2D; The Rigidbody2D component attached to this object.

private float inverseMoveTime; Used to make movement more efficient.

Protected, virtual functions can be overridden by inheriting classes.

Get a component reference to this object's BoxCollider2D

Get a component reference to this object's Rigidbody2D

By storing the reciprocal of the move time we can use it by multiplying instead of dividing, this is more efficient.

Move returns true if it is able to move and false if not.

Move takes parameters for x direction, y direction and a RaycastHit2D to check collision.

Store start position to move from, based on objects current transform position.

Calculate end position based on the direction parameters passed in when calling Move.

Disable the boxCollider so that linecast doesn't hit this object's own collider.

Cast a line from start point to end point checking collision on blockingLayer.

Re-enable boxCollider after linecast

Check if anything was hit

If nothing was hit, start SmoothMovement co-routine passing in the Vector2 end as destination

Return true to say that Move was successful

If something was hit, return false, Move was unsuccesful.

Co-routine for moving units from one space to next, takes a parameter end to specify where to move to.

Calculate the remaining distance to move based on the square magnitude of the difference between current position and end parameter.

Square magnitude is used instead of magnitude because it's computationally cheaper.

While that distance is greater than a very small amount (Epsilon, almost zero):

Find a new position proportionally closer to the end, based on the moveTime

Call MovePosition on attached Rigidbody2D and move it to the calculated position.

Recalculate the remaining distance after moving.

Return and loop until sqrRemainingDistance is close enough to zero to end the function

The virtual keyword means AttemptMove can be overridden by inheriting classes using the override keyword.

AttemptMove takes a generic parameter T to specify the type of component we expect our unit to interact with if blocked (Player for Enemies, Wall for Player).

Hit will store whatever our linecast hits when Move is called.

Set canMove to true if Move was successful, false if failed.

Check if nothing was hit by linecast

If nothing was hit, return and don't execute further code.

Get a component reference to the component of type T attached to the object that was hit

If canMove is false and hitComponent is not equal to null, meaning MovingObject is blocked and has hit something it can interact with.

Call the OnCantMove function and pass it hitComponent as a parameter.

The abstract modifier indicates that the thing being modified has a missing or incomplete implementation.

OnCantMove will be overriden by functions in the inheriting classes.




Trò chơi giống như Rogue 2D sử dụng Unity 28.457 lượt xem

Gõ tìm kiếm nhanh...